home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 1 / PC Actual CD 01.iso / f1 / cimb.arj / IMG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-19  |  11.8 KB  |  577 lines

  1. /*==============================================================================
  2.  
  3. FICHERO: IMG.C
  4.  
  5. AUTOR: ANTONIO LADESA JURADO
  6.  
  7. FECHA: 24/6/94
  8.  
  9. DESCRIPCION:
  10.  
  11.     Fichero que contiene las estructuras, constantes, variables y funciones
  12.     internas y externas para el procesamiento de ficheros IMG.
  13.  
  14. ==============================================================================*/
  15.  
  16.  
  17. /*---- MODULOS USADOS --------------------------------------------------------*/
  18.  
  19. #include <stdio.h>
  20. #include <alloc.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23.  
  24. #include "global.h"
  25. #include "memoria.h"
  26. #include "video.h"
  27. #include "img.h"
  28. #include "error.h"
  29.  
  30. /*---- ESTRUCTURAS, CONSTANTES Y VARIABLES LOCALES AL MODULO -----------------*/
  31.  
  32.  
  33. typedef struct
  34.     {
  35.     int id1;
  36.     int id2;
  37.     int planos;
  38.     int longitud;
  39.     int ancho_pixels;
  40.     int alto_pixels;
  41.     int ancho_linea;
  42.     int alto_imagen;
  43.     }
  44. CABimg;
  45.  
  46.     /* longitud del patron de lectura */
  47. static int long_patron;
  48.     /* lineas a repetir */
  49. static int lineas;
  50.  
  51.  
  52. /*---- DEFINICION DE LAS FUNCIONES INTERNAS ----------------------------------*/
  53.  
  54.  
  55. IMAGEN *IMGleerCabecera(IMAGEN *c,FILE *f,char *nombre);
  56. IMAGEN *IMGleerImagen(IMAGEN *c,FILE *);
  57. int IMGleerLinea(char *,FILE *,int);
  58.  
  59. char *IMGcrearCabecera(IMAGEN *c,char *cabaux);
  60. int IMGescribirLinea(char *p,FILE *f,int bytes);
  61. int IMGescribirImagen(IMAGEN *c,FILE *f);
  62.  
  63. /*---- CODIFICACION DE LAS FUNCIONES OFRECIDAS -------------------------------*/
  64.  
  65.  
  66. /*---- FUNCION: extern IMAGEN *IMGcargar(char *nombre,IMAGEN *c) ---------------
  67.  
  68.     Descripción:
  69.  
  70.         Esta función carga en memoria una imagen de tipo IMG.
  71.  
  72.     Parámetros:
  73.  
  74.         char *nombre : nombre del fichero a cargar
  75.         IMAGEN *c : puntero a estructura que alberga la imagen
  76.  
  77.     Retorno:
  78.  
  79.         Puntero a la estructura de la imagen o NULL si hubo error
  80.  
  81. ---- CODIGO: -----------------------------------------------------------------*/
  82.  
  83. extern IMAGEN *IMGcargar(char *nombre,IMAGEN *c)
  84. {
  85.     /* puntero al fichero */
  86. FILE *f;
  87.  
  88.     /* abrir el fichero */
  89. if((f = fopen(nombre, "rb")) != NULL)
  90.     {
  91.         /* leer cabecera IMG */
  92.     if((c = IMGleerCabecera(c,f,nombre))!=NULL)
  93.             /* leer imagen */
  94.         c = IMGleerImagen(c,f);
  95.     fclose(f);
  96.     }
  97. else
  98.     {
  99.     ERRORponer(ERRapertura);
  100.     return(NULL);
  101.     }
  102. return(c);
  103. }
  104.  
  105. /*---- FIN FUNCION -----------------------------------------------------------*/
  106.  
  107.  
  108. /*---- FUNCION: extern int *IMGsalvar(char *nombre,IMAGEN *c) ------------------
  109.  
  110.     Descripción:
  111.  
  112.         Esta función salva en disco una imagen con formato IMG.
  113.  
  114.     Parámetros:
  115.  
  116.         char *nombre : nombre del fichero a salvar
  117.         IMAGEN *c : puntero a estructura que alberga la imagen
  118.  
  119.     Retorno:
  120.  
  121.         - 0 si hay error
  122.         - 1 en caso contrario
  123.  
  124. ---- CODIGO: -----------------------------------------------------------------*/
  125.  
  126.     /* salvar un fichero IMG */
  127. extern int IMGsalvar(char *nombre,IMAGEN *c)
  128. {
  129.     /* array auxiliar */
  130. char cabaux[16];
  131.     /* puntero al fichero */
  132. FILE *f;
  133.     /* cabecera del fichero IMG */
  134. CABimg cabecera;
  135.  
  136.     /* abrir el fichero */
  137. if((f = fopen(nombre, "wb")) == NULL)
  138.     {
  139.     ERRORponer(ERRapertura);
  140.     return(0);
  141.     }
  142.  
  143.     /* adecuar el modo de vídeo a la imagen */
  144. if(c->modo == VIDEOvga)
  145.     c=VIDEOvision(c);
  146.  
  147.     /* crear la cabecera IMG */
  148. memcpy((char *)&cabecera,IMGcrearCabecera(c,cabaux),16);
  149.     /* escribir la cabecera IMG */
  150. if(fwrite((char *)&cabecera,1,sizeof(cabecera),f) != sizeof(cabecera))
  151.     {
  152.     ERRORponer(ERRescritura);
  153.     return(0);
  154.     }
  155.     /* escribir la imagen IMG */
  156. IMGescribirImagen(c,f);
  157. fclose(f);
  158. return(1);
  159. }
  160.  
  161. /*---- FIN FUNCION -----------------------------------------------------------*/
  162.  
  163.  
  164. /*---- CODIFICACION DE LAS FUNCIONES INTERNAS --------------------------------*/
  165.  
  166.  
  167. /*---- FUNCION: IMAGEN *IMGleerCabecera(IMAGEN *c,FILE *f,char *nombre) --------
  168.  
  169.     Descripción:
  170.  
  171.         Esta función reserva memoria para la imagen y lee la cabecera del fichero
  172.         IMG.
  173.  
  174.     Parámetros:
  175.  
  176.  
  177.         IMAGEN *c : puntero a estructura que alberga la imagen
  178.         FILE *f : puntero al fichero
  179.         char *nombre : nombre del fichero a cargar
  180.  
  181.     Retorno:
  182.  
  183.         Puntero a la estructura de la imagen o NULL si hubo error
  184.  
  185. ---- CODIGO: -----------------------------------------------------------------*/
  186.  
  187. IMAGEN *IMGleerCabecera(IMAGEN *c,FILE *f,char *nombre)
  188. {
  189.     /* array auxiliar */
  190. char cabaux[16];
  191.     /* cabecera del fichero IMG */
  192. CABimg cabecera;
  193.  
  194.     /* leer cabecera IMG */
  195. if(fread((char *)&cabaux,1,sizeof(cabecera),f) == sizeof(cabecera))
  196.     {
  197.         /* comprobar que es IMG */
  198.     if(memcmp("\x00\x01\x00\x08",cabaux,4))
  199.         {
  200.         ERRORponer(ERRnoTratado);
  201.         return(NULL);
  202.         }
  203.     }
  204. else
  205.     {
  206.     ERRORponer(ERRlectura);
  207.     return(NULL);
  208.     }
  209.     /* los enteros vienen en formato MOTOROLA, cambiarlos */
  210. swab(cabaux,(char *)&cabecera,16);
  211.  
  212.     /* reservar memoria para la cabecera de trabajo */
  213. if((c=MEMreservarCAB(c))==NULL)
  214.     {
  215.     ERRORponer(ERRnoMemoria);
  216.     return(NULL);
  217.     }
  218.     /* cargar cabecera de trabajo */
  219. strcpy(c->nombre,nombre);
  220. c->ancho = cabecera.ancho_linea;
  221. c->alto = cabecera.alto_imagen;
  222. c->formato = IMG;
  223. c->haypaleta = FALSO;
  224.     /* determinar tipo de imagen */
  225. switch(cabecera.planos)
  226.     {
  227.         /* monocromática */
  228.     case 1:
  229.         c->modo = VIDEOmono;
  230.         c->colores = 2;
  231.         c->bytes = DePixelsABytes(c->ancho);
  232.     break;
  233.  
  234.         /* 16 grises */
  235.     case 4:
  236.         c->modo = VIDEOega;
  237.         c->colores = 16;
  238.         c->bytes = DePixelsABytes(c->ancho) * 4;
  239.     break;
  240.         /* 256 grises */
  241.     case 8:
  242.         c->modo = VIDEOvga;
  243.         c->colores = 256;
  244.         c->bytes = c->ancho;
  245.     break;
  246.  
  247.     default:
  248.         /* formato desconocido */
  249.         ERRORponer(ERRnoTratado);
  250.         c = MEMliberar(c);
  251.     return(c);
  252.     }
  253.     /* patron de lectura */
  254. long_patron = cabecera.longitud;
  255.  
  256.     /* si no hay memoria para la imagen, liberar cabecera */
  257. if(!MEMreservar(c))
  258.     {
  259.     c =MEMliberar(c);
  260.     ERRORponer(ERRnoMemoria);
  261.     return(c);
  262.     }
  263. return(c);
  264. }
  265.  
  266. /*---- FIN FUNCION -----------------------------------------------------------*/
  267.  
  268.  
  269. /*---- FUNCION: IMAGEN *IMGleerImagen(IMAGEN *c,FILE *f) -----------------------
  270.  
  271.     Descripción:
  272.  
  273.         Esta función carga en memoria una imagen de tipo IMG.
  274.  
  275.     Parámetros:
  276.  
  277.  
  278.         IMAGEN *c : puntero a estructura que alberga la imagen
  279.         FILE *f : puntero al fichero
  280.  
  281.     Retorno:
  282.  
  283.         Puntero a la estructura de la imagen
  284.  
  285. ---- CODIGO: -----------------------------------------------------------------*/
  286.  
  287. IMAGEN *IMGleerImagen(IMAGEN *c,FILE *f)
  288. {
  289.     /* contador de líneas */
  290. int i;
  291.     /* buffers de lectura */
  292. char p[ANCHO_MAXIMO];
  293. char q[ANCHO_MAXIMO];
  294.  
  295. lineas = 1;
  296.     /* cargar imagen */
  297. for(i = 0; i < c->alto ;)
  298.     {
  299.     if(c->modo == VIDEOvga)
  300.         {
  301.         IMGleerLinea(q,f,c->bytes);
  302.             /* la imagen viene codificada por planos */
  303.         VGAdePlanoaPixel(q,p,c->ancho);
  304.         }
  305.     else
  306.         IMGleerLinea(p,f,c->bytes);
  307.         /* llevar a memoria la(s) línea(s) */
  308.     while(lineas--)
  309.         {
  310.         MEMescribir(p,i,c);
  311.         ++i;
  312.         }
  313.     }
  314. return(c);
  315. }
  316.  
  317. /*---- FIN FUNCION -----------------------------------------------------------*/
  318.  
  319.  
  320. /*---- FUNCION: void IMGleerLinea(char *p, FILE *f,int bytes) ------------------
  321.  
  322.     Descripción:
  323.  
  324.         Esta función lee una línea de un fichero IMG.
  325.  
  326.     Parámetros:
  327.  
  328.         char *p : puntero a buffer donde se almacena la línea
  329.         FILE *f : puntero al fichero
  330.         int bytes: numero de bytes por linea
  331.  
  332. ---- CODIGO: -----------------------------------------------------------------*/
  333.  
  334. int IMGleerLinea(char *p,FILE *f,int bytes)
  335. {
  336.     /* puntero a la primera posición libre */
  337. char *pr;
  338.     /* contadores */
  339. int j,k,n=0,i;
  340.     /* byte a tratar */
  341. int c;
  342.  
  343. memset(p,0,bytes);
  344. lineas = 1;
  345.  
  346. do
  347.     {
  348.         /* leer byte */
  349.     c = fgetc(f) & 0xff;
  350.         /* si es cero... */
  351.     if(c==0)
  352.         {
  353.             /* leer siguiente */
  354.         c=fgetc(f) & 0xff;
  355.             /* si es cero, se trata de una línea repetida */
  356.         if(c==0)
  357.             {
  358.                 /* leer 0xff */
  359.             fgetc(f);
  360.                 /* guardar numero de líneas */
  361.             lineas = fgetc(f) & 0xff;
  362.             }
  363.         else
  364.             {
  365.                 /* si no es cero, es un 'pattern run' */
  366.                 /* leer numero de repeticiones del patrón */
  367.             i=c & 0xff;
  368.                 /* buffer de repetición */
  369.             pr=p+n;
  370.                 /* leer del fichero el patrón a repetir */
  371.             j=long_patron;
  372.             while(j--)
  373.                 p[n++]=~fgetc(f);
  374.                 /* repetir el patrón */
  375.             k=i-1;
  376.             while(k--)
  377.                 {
  378.                 memcpy(p+n,pr,long_patron);
  379.                 n+=long_patron;
  380.                 }
  381.             }
  382.         }
  383.     else
  384.             /* si vale 0x80, es un 'bit string' */
  385.         if(c==0x80)
  386.             {
  387.             i=fgetc(f) & 0xff;
  388.                 /* leer contador */
  389.             pr=p+n;
  390.             j=i;
  391.                 /* leer los bytes del fichero */
  392.             while(j--)
  393.                 p[n++]=~fgetc(f);
  394.             }
  395.         else
  396.                 /* leer bytes de color negro */
  397.             if(c & 0x80)
  398.                 {
  399.                     /* determinar numero de bytes */
  400.                 i = c & 0x7f;
  401.                 pr = p+n;
  402.                 j=i;
  403.                     /* repetirlos */
  404.                 while(j--)
  405.                     p[n++]=~0xff;
  406.                 }
  407.             else
  408.                 /* leer bytes de color blanco */
  409.                 {
  410.                     /* determinar numero de bytes */
  411.                 i=c &0x7f;
  412.                 pr =p+n;
  413.                 j=i;
  414.                     /* repetirlos */
  415.                 while(j--)
  416.                     p[n++]=~0x00;
  417.                 }
  418.     }
  419. while(n < bytes);
  420. return(n);
  421. }
  422.  
  423. /*---- FIN FUNCION -----------------------------------------------------------*/
  424.  
  425.  
  426. /*---- FUNCION: void IMGcrearCabecera(IMAGEN *c) -------------------------------
  427.  
  428.     Descripción:
  429.  
  430.         Esta función crea una cabecera IMG.
  431.  
  432.     Parámetros:
  433.  
  434.         IMAGEN *c : puntero a estructura que alberga la imagen
  435.  
  436. ---- CODIGO: -----------------------------------------------------------------*/
  437.  
  438. char *IMGcrearCabecera(IMAGEN *c,char *cabaux)
  439. {
  440. memcpy(cabaux,"\x00\x01\x00\x08\x00\x01\x00\x01\x00\x55\x00\x55",12);
  441. cabaux[13] = c->ancho & 0xff;
  442. cabaux[12] = (c->ancho & 0xff00) >> 8;
  443. cabaux[15] = c->alto & 0xff;
  444. cabaux[14] = (c->alto & 0xff00) >> 8;
  445.  
  446. switch(c->modo)
  447.     {
  448.     case VIDEOmono:cabaux[5] = 1;break;
  449.     case VIDEOega: cabaux[5] = 4;break;
  450.     case VIDEOvga: cabaux[5] = 8;break;
  451.     }
  452. return(cabaux);
  453. }
  454.  
  455. /*---- FIN FUNCION -----------------------------------------------------------*/
  456.  
  457.  
  458. /*---- FUNCION: void IMGescribirImagen(IMAGEN *c,FILE *f) ----------------------
  459.  
  460.     Descripción:
  461.  
  462.         Esta función graba la imagen en un fichero IMG.
  463.  
  464.     Parámetros:
  465.  
  466.         IMAGEN *c : puntero a estructura que alberga la imagen
  467.         FILE *f : puntero al fichero
  468.  
  469. ---- CODIGO: -----------------------------------------------------------------*/
  470.  
  471. int IMGescribirImagen(IMAGEN *c,FILE *f)
  472. {
  473. int i;
  474. char p[ANCHO_MAXIMO];
  475. char q[ANCHO_MAXIMO];
  476.  
  477.     /* salvar imagen */
  478. for(i = 0; i < c->alto;i++)
  479.     {
  480.     if(c->modo == VIDEOvga)
  481.         {
  482.         MEMleer(q,i,c);
  483.             /* codificar por plano */
  484.         VGAdePixelaPlano(q,p,c->ancho);
  485.         }
  486.     else
  487.         MEMleer(p,i,c);
  488.     IMGescribirLinea(p,f,c->bytes);
  489.     }
  490. return(1);
  491. }
  492.  
  493. /*---- FIN FUNCION -----------------------------------------------------------*/
  494.  
  495.  
  496. /*---- FUNCION: void IMGescribirLinea(char *p, FILE *f,int bytes) --------------
  497.  
  498.     Descripción:
  499.  
  500.         Esta función escribe una línea en un fichero IMG.
  501.  
  502.     Parámetros:
  503.  
  504.         char *p : puntero a buffer que alberga la línea
  505.         FILE *f : puntero al fichero
  506.         int bytes : numero de bytes por línea
  507.  
  508.     Retorno:
  509.  
  510.         Puntero a la estructura de la imagen o NULL si hubo error
  511.  
  512. ---- CODIGO: -----------------------------------------------------------------*/
  513.  
  514. int IMGescribirLinea(char *p,FILE *f,int bytes)
  515. {
  516. int bdex=0,i=0,j=0,t=0;
  517. char b[ANCHO_MAXIMO];
  518. do
  519.     {
  520.     i=0;
  521.     while((p[t+i]==p[t+i+1]) && ((t+i) < (bytes-1)) && i < 0x7e)
  522.         ++i;
  523.     if(i>0 || bdex >= 0x7e)
  524.         {
  525.         if(bdex)
  526.             {
  527.                 /* bit string */
  528.             fputc(0x80,f);
  529.             fputc(bdex,f);
  530.             j+=2;
  531.             fwrite(b,1,bdex,f);
  532.             j+=bdex;
  533.             bdex=0;
  534.             }
  535.         if(i)
  536.             {
  537.                 /* byte blanco */
  538.             if(p[t+i]==0xff)
  539.                 {
  540.                 fputc(i+1,f);
  541.                 j++;
  542.                 }
  543.             else
  544.                     /* byte negro */
  545.                 if(p[t+i]==0x00)
  546.                     {
  547.                     fputc(i+1+0x80,f);
  548.                     j++;
  549.                     }
  550.                 else
  551.                     {
  552.                         /* pattern run */
  553.                     fputc(0x00,f);
  554.                     fputc(i+1,f);
  555.                     fputc(~p[t+i],f);
  556.                     j+=3;
  557.                     }
  558.             t+=(i+1);
  559.             }
  560.         }
  561.     else
  562.         b[bdex++]=~p[t++];
  563.     }while(t<bytes);
  564.  
  565.     /* bit string pendiente */
  566. if(bdex)
  567.     {
  568.     fputc(0x80,f);
  569.     fputc(bdex,f);
  570.     j+=2;
  571.     fwrite(b,1,bdex,f);
  572.     j+=bdex;
  573.     }
  574. return(bytes);
  575. }
  576.  
  577. /*---- FIN FUNCION -----------------------------------------------------------*/